"""
PROJECT: dsocket
FILE: consumers.py
AUTHOR: wensen
CREATE: 2022-02-16
websocket 处理文件
"""

import json
import random

from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer, AsyncWebsocketConsumer


# 同步
class ChatConsumer(WebsocketConsumer):
    room_name = ""
    room_group_name = ""

    # 新的socket函数，支持广播
    def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'chat_%s' % self.room_name

        # async_to_sync 异步变同步
        # 加入房间组
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )

        self.accept()

    def disconnect(self, close_code):
        # 离开房间组
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    # 从 WebSocket 接收消息
    def receive(self, text_data=None, bytes_data=None):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        event = {
            'type': 'chat_message',
            'message': message
        }
        # 向房间组发送消息
        async_to_sync(self.channel_layer.group_send)(self.room_group_name, event)

    # 接收来自房间组的消息
    def chat_message(self, event):
        message = event['message']
        # 向 WebSocket 发送消息
        self.send(text_data=json.dumps({
            'message': message
        }))


# 异步
class AsyncChatConsumer(AsyncWebsocketConsumer):
    room_name = ""
    room_group_name = ""
    username = ""

    # 创建链接
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'chat_%s' % self.room_name
        self.username = random.randint(0000, 9999)
        # 加入房间组
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )
        await self.accept()

    # 断开链接
    async def disconnect(self, close_code):
        # 离开房间组
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    # 从 WebSocket 接收消息
    async def receive(self, text_data=None, bytes_data=None):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        event = {
            'type': 'chat_message',
            'data': {
                "message": message,
                "username": self.username
            }
        }
        # 向房间组发送消息
        await self.channel_layer.group_send(self.room_group_name, event)

    # 接收来自房间组的消息
    async def chat_message(self, event):
        data = event['data']
        # 向 WebSocket 发送消息
        await self.send(text_data=json.dumps({
            "message": data["message"],
            "username": data["username"]
        }))


# 公告即时通知
class AsyncAnnouncementConsumer(AsyncWebsocketConsumer):
    group_name = "announcement"

    # 创建链接
    async def connect(self):
        # 加入组
        await self.channel_layer.group_add(
            self.group_name,
            self.channel_name
        )
        await self.accept()

    # 断开链接
    async def disconnect(self, close_code):
        # 离开房间组
        await self.channel_layer.group_discard(
            self.group_name,
            self.channel_name
        )

    # 从 WebSocket 接收消息
    async def receive(self, text_data=None, bytes_data=None):
        text_data_json = json.loads(text_data)
        code = text_data_json['code']
        message = text_data_json['message']
        if code == 1000:
            # 将消息发送回组内
            event = {
                'type': 'push_message',
                "message": {
                    "code": 3000,
                    "message": message
                },
            }
            await self.channel_layer.group_send(self.group_name, event)

    # 推送消息
    async def push_message(self, event):
        message = event['message']
        await self.send(text_data=json.dumps(message))


# 服务器推送消息
class ServiceAsyncWebsocketConsumer(AsyncWebsocketConsumer):
    group_name = "123"

    # 创建链接
    async def connect(self):
        print(self.scope)
        # 加入房间组
        await self.channel_layer.group_add(self.group_name, self.channel_name)
        await self.accept()
        print(self.scope["client"])

    # 断开链接
    async def disconnect(self, close_code):
        print(close_code)
        print(self.scope["client"])
        # 离开房间组
        await self.channel_layer.group_discard(self.group_name, self.channel_name)

    # 推送消息到组内
    async def push_message(self, event):
        message = event['message']
        await self.send(text_data=json.dumps(message))
